package com.cjl.host.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cjl.common.constants.HostFoodRelationsLogMessageConstants;
import com.cjl.common.constants.LoginStatusConstants;
import com.cjl.common.dtos.LoginDto;
import com.cjl.common.dtos.PageDto;
import com.cjl.common.dtos.ResponseResult;
import com.cjl.common.enums.HttpEnums;
import com.cjl.feign.food.FoodClient;
import com.cjl.food.dtos.FoodDto;
import com.cjl.host.mapper.HostMapper;
import com.cjl.host.pojos.Host;
import com.cjl.host.service.HostFoodRelationsService;
import com.cjl.host.service.HostService;
import com.cjl.utils.common.JwtUtil;
import com.cjl.utils.common.RandomStrUtil;
import com.cjl.utils.thread.HostThreadUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author cjl
 * @version v1.0
 * @description TODO
 * @createTime 2023/2/15 12:17
 */

@Component
@Transactional
@Slf4j
public class HostServiceImpl extends ServiceImpl<HostMapper, Host> implements HostService {


    /**
     * 登录/注册
     *
     * @param hostLoginDto 店主登录dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult login(LoginDto hostLoginDto) {
        //检查参数
        boolean result = checkParams(hostLoginDto);
        if (result) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID);

        //获取参数
        String phone = hostLoginDto.getPhone();
        String password = hostLoginDto.getPassword();
        Short status = hostLoginDto.getStatus();

        //根据手机号获取用户
        Host dbHost = getHostByPhone(phone);

        //判断是登录还是注册
        if (status == LoginStatusConstants.REGISTER) {
            //注册
            //判断店家是否存在
            if (dbHost != null) return ResponseResult.errorResult(HttpEnums.HOST_ALREADY_EXIST);

            //MD5加密
            String salt = RandomStrUtil.randomStr();
            password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
            Host newHost = Host.builder()
                    .phone(phone)
                    .password(password)
                    .salt(salt)
                    .createdTime(new Date())
                    .build();
            //保存数据到mysql
            boolean saveResult = save(newHost);
            if (!saveResult) return ResponseResult.errorResult(HttpEnums.DB_UPDATE_DATA_ERROR, "店家注册失败");

            //屏蔽敏感信息
            blockSensitiveMessage(newHost);
            return ResponseResult.okResult(newHost);

        } else if (status == LoginStatusConstants.LOGIN) {
            //登录
            //判断店家是否存在
            if (dbHost == null) return ResponseResult.errorResult(HttpEnums.HOST_NOT_EXIST);

            String salt = dbHost.getSalt();
            String dbHostPassword = dbHost.getPassword();
            //核对密码
            if (!dbHostPassword.equals(DigestUtils.md5DigestAsHex((password + salt).getBytes())))
                return ResponseResult.errorResult(HttpEnums.DB_PASSWORD_ERROR);

            //根据id生成token
            String token = JwtUtil.getToken(dbHost.getId().longValue());
            //屏蔽敏感信息
            blockSensitiveMessage(dbHost);

            //返回数据
            Map<String, Object> data = new HashMap<>();
            data.put("host", dbHost);
            data.put("token", token);
            return ResponseResult.okResult(data);

        } else {
            return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID);
        }
    }

    /**
     * 屏蔽敏感信息
     *
     * @param newHost 店主
     */
    private void blockSensitiveMessage(Host newHost) {
        newHost.setId(null);
        newHost.setPassword(null);
        newHost.setSalt(null);
    }

    /**
     * 根据手机号获取店主
     *
     * @param phone 手机号
     * @return Host
     */
    private Host getHostByPhone(String phone) {
        return getOne(new LambdaQueryWrapper<Host>().eq(Host::getPhone, phone));
    }

    /**
     * 检查参数
     *
     * @param hostLoginDto 店主登录dto
     * @return boolean
     */
    private boolean checkParams(LoginDto hostLoginDto) {
        return hostLoginDto == null
                || StringUtils.isBlank(hostLoginDto.getPhone())
                || StringUtils.isBlank(hostLoginDto.getPassword())
                || hostLoginDto.getStatus() == null;
    }

    /**
     * 修改密码
     *
     * @param hostLoginDto 店主登录dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult modifyPassword(LoginDto hostLoginDto) {
        //校验参数
        boolean result = checkParams(hostLoginDto);
        if (result) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID);
        if (hostLoginDto.getStatus() != 2) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID);

        //获取参数
        String phone = hostLoginDto.getPhone();
        String password = hostLoginDto.getPassword();

        //根据手机号获取用户
        Host dbHost = getHostByPhone(phone);

        //判断店家是否存在
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.HOST_NOT_EXIST);

        //获取盐值
        String salt = dbHost.getSalt();
        password = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        dbHost.setPassword(password);
        //最近一次修改时间
        dbHost.setUpdatedTime(new Date());

        //更新到数据库
        boolean updateResult = updateById(dbHost);

        if (!updateResult) return ResponseResult.errorResult(HttpEnums.DB_UPDATE_DATA_ERROR);

        //屏蔽敏感信息
        blockSensitiveMessage(dbHost);
        return ResponseResult.okResult(dbHost);
    }

    /**
     * 修改店名
     *
     * @param hostName 店主名
     * @return ResponseResult
     */
    @Override
    public ResponseResult modifyHostName(String hostName) {
        //检查参数
        if (StringUtils.isBlank(hostName)) return ResponseResult.errorResult(HttpEnums.PARAMS_INVALID, "店名无效");

        //获取id
        Integer hostId = HostThreadUtil.get().getId();

        //根据判断是否是正常操作
        if (hostId == null) return ResponseResult.errorResult(HttpEnums.UN_AUTHORIZE);
        Host dbHost = getById(hostId);
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.HOST_NOT_EXIST);

        //更新数据到数据库
        dbHost.setName(hostName);
        //最近一次修改时间
        dbHost.setUpdatedTime(new Date());
        boolean result = updateById(dbHost);

        //判断是否更新成功
        if (!result) return ResponseResult.errorResult(HttpEnums.DB_UPDATE_DATA_ERROR, "店名修改失败");

        //屏蔽敏感信息
        blockSensitiveMessage(dbHost);
        return ResponseResult.okResult(dbHost);
    }

    @Autowired
    FoodClient foodClient;


    @Autowired
    HostFoodRelationsService hostFoodRelationsService;

    /**
     * 添加菜品
     *
     * @param foodDto 菜品dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult addFood(FoodDto foodDto) {
        //获取店主
        Host dbHost = getHost();

        //检查用户身份有效性
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.UN_AUTHORIZE, "用户不存在，非法操作");
        log.info(Thread.currentThread().getName() + "。。。");

        log.info("用户{}添加菜品数据中。。。", dbHost.getName());
        ResponseResult responseResult = foodClient.addFood(foodDto);

        //用户行为记录
        hostFoodRelationsService.hostFoodRelationRecord(dbHost,
                responseResult,
                "用户{}添加数据失败。。。",
                HostFoodRelationsLogMessageConstants.INSERT,
                HostFoodRelationsLogMessageConstants.INSERT_MESSAGE
        );
        return responseResult;
    }


    /**
     * 根据ThreadLocal中的id获取店主
     *
     * @return Host
     */
    private Host getHost() {
        Integer hostId = HostThreadUtil.get().getId();
        return getById(hostId);
    }

    @Override
    public ResponseResult deleteFood(String foodName) {
        //获取店主
        Host dbHost = getHost();

        //检查用户身份有效性
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.UN_AUTHORIZE, "用户不存在，非法操作");

        log.info("用户{}删除菜品数据中。。。", dbHost.getName());
        ResponseResult responseResult = foodClient.deleteFood(foodName);

        //用户行为记录
        hostFoodRelationsService.hostFoodRelationRecord(dbHost,
                responseResult,
                "用户{}删除数据失败。。。",
                HostFoodRelationsLogMessageConstants.DELETE,
                HostFoodRelationsLogMessageConstants.DELETE_MESSAGE
        );
        return responseResult;
    }


    /**
     * 修改菜品
     *
     * @param foodDto 菜品dto
     * @return ResponseResult
     */
    @Override
    public ResponseResult modifyFood(FoodDto foodDto) {
        //获取店主
        Host dbHost = getHost();

        //检查用户身份有效性
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.UN_AUTHORIZE, "用户不存在，非法操作");

        log.info("用户{}修改菜品数据中。。。", dbHost.getName());
        ResponseResult responseResult = foodClient.modifyFood(foodDto);

        //用户行为记录
        hostFoodRelationsService.hostFoodRelationRecord(dbHost,
                responseResult,
                "用户{}修改数据失败。。。",
                HostFoodRelationsLogMessageConstants.UPDATE,
                HostFoodRelationsLogMessageConstants.UPDATE_MESSAGE
        );

        return responseResult;
    }

    /**
     * 根据菜名查询菜品
     *
     * @param foodName 菜名
     * @return ResponseResult
     */
    @Override
    public ResponseResult searchFood(String foodName) {
        //获取店主
        Host dbHost = getHost();

        //检查用户身份有效性
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.UN_AUTHORIZE, "用户不存在，非法操作");

        log.info("用户{}查询菜品中。。。", dbHost.getName());
        return foodClient.searchFood(foodName);
    }

    @Autowired
    RedisTemplate<String, ResponseResult> redisTemplate;

    /**
     * 菜品列表
     *
     * @param pageDto 分页参数
     * @return ResponseResult
     */
    @Override
    public ResponseResult foodList(PageDto pageDto) {
        //获取店主
        Host dbHost = getHost();

        //检查用户身份有效性
        if (dbHost == null) return ResponseResult.errorResult(HttpEnums.UN_AUTHORIZE, "用户不存在，非法操作");

        log.info("用户{}查询菜品列表中。。。", dbHost.getName());

        //查询菜品列表
        return foodClient.foodList(pageDto);

    }
}
